#ifndef _INCLUDED_SERIALIZE_H_
#define _INCLUDED_SERIALIZE_H_


template<unsigned int SZ > struct type_of_num_bytes;
template<>
struct type_of_num_bytes<1>{
	typedef unsigned char type;
};
template<>
struct type_of_num_bytes<2>{
	typedef unsigned short type;
};
template<>
struct type_of_num_bytes<4>{
	typedef unsigned int type;
};

template<typename T,unsigned int SZ = 4>
class serializable_sequence{
	T self_;
public:
	typedef typename T::value_type value_type;
	enum{num_size_bytes = SZ};
	typedef typename type_of_num_bytes<SZ>::type size_type;
	
	serializable_sequence(){}
	explicit serializable_sequence(const T& seq):self_(seq){}
	operator T()const{return self_;}

	void push_back(const value_type& v){self_.push_back(v);}
	size_type size()const {return (size_type)self_.size();}
	const value_type& operator[](size_type idx)const{return self_[idx];}
	value_type& operator[](size_type idx){return self_[idx];}
};
//to be 0x
//template<typename T> using small_sequence = serializable_sequence<T,1>;
//template<typename T> using short_sequence = serializable_sequence<T,2>;

inline void serialize(int i,std::vector<char> *mem)
{
	size_t sz = mem->size();
	mem->resize(sz + sizeof(int));
	*reinterpret_cast<int*>(&(*mem)[0] + sz) = i;
}
inline void serialize(unsigned int i,std::vector<char> *mem)
{
	size_t sz = mem->size();
	mem->resize(sz + sizeof(unsigned int));
	*reinterpret_cast<unsigned int*>(&(*mem)[0] + sz) = i;
}
inline void serialize(char c,std::vector<char> *mem)
{
	mem->push_back(c);
}
template<typename SeqT,int SZ>
inline void serialize(const serializable_sequence<SeqT,SZ>& seq,std::vector<char> *mem)
{
	typedef serializable_sequence<SeqT,SZ> sequence_type;
	typedef typename sequence_type::size_type size_type;
	size_t sz = mem->size();
	mem->resize(sz + sequence_type::num_size_bytes);
	*reinterpret_cast<size_type*>(&(*mem)[0] + sz) = seq.size();
	//change to iterator
	for(size_type i = 0 ;i < seq.size(); ++i)
	{
		serialize(seq[i], mem);
	}
}
inline bool deserialize(const char** mem,int *size,char *c)
{
	if(*size > 0)
	{
		*c = **mem;
		(*mem) ++;
		*size --;
		return true;
	}
	return false;
}
template<typename SeqT>
bool deserialize_seq_impl(const char** mem,int *size,unsigned sz,SeqT* r)
{
	typedef typename SeqT::value_type value_type;
	value_type elem;
	while(sz-- > 0 )
	{
		if(deserialize(mem,size,&elem))
			r->push_back(elem);
		else
			return false;
	}
	return true;
}

template<typename SeqT,int SZ> 
bool deserialize(const char** mem,int *size,serializable_sequence<SeqT,SZ> *r)
{
	typedef serializable_sequence<SeqT,SZ> sequence_type;
	typedef typename sequence_type::size_type size_type;
	if (*size >= sequence_type::num_size_bytes)
	{
		size_type sz = *((size_type*)(*mem));
		(*mem) += sequence_type::num_size_bytes;
		*size -= sequence_type::num_size_bytes;
		return deserialize_seq_impl(mem,size,sz,r);
	}
	else return false;
}

template<typename R0>
bool deserialize(const char** mem,int *size,R0 *r)
{
	assert(false);
}
template<typename R0,typename R1>
bool deserialize(const char** mem,int *size,R0 *r0, R1 *r1)
{
	return deserialize(mem,size,r0) &&
	deserialize(mem,size,r1);
}
template<typename R0,typename R1,typename R2>
bool deserialize(const char** mem,int *size,R0 *r0, R1 *r1,R2 *r2)
{
	return deserialize(mem,size,r0,r1) &&
	deserialize(mem,size,r2);
}

#endif